#!/usr/bin/env ruby

# = Redis-Dump
#
#
# Usage:
#
#     $ redis-dump -h
#     $ redis-dump > dumpfile_full.json
#     $ redis-dump -d 15 > dumpfile_db15.json
#
#--

RD_HOME = File.expand_path File.join(File.dirname(__FILE__), '..')
lib_dir = File.join(RD_HOME, 'lib')
$:.unshift lib_dir

require 'redis/dump'
require 'drydock'

# Command-line interface for bin/redis-dump
class Redis::Dump::CLI
  extend Drydock

  default :dump
  trawler :dump

  global :u, :uri, String, "Redis URI (e.g. redis://hostname[:port])"
  global :d, :database, Integer, "Redis database (e.g. -d 15)"
  global :a, :password, String, "Redis password (e.g. -a 'my@pass/word')" do |v|
    Redis::Dump.password = v
  end
  global :t, :timeout, Integer, "Configure connect, read, and write timeouts (ruby redis client)" do |t|
    Redis::Dump.timeout = t
  end
  global :s, :sleep, Integer, "Sleep for S seconds after dumping (for debugging)"
  global :c, :count, Integer, "Chunk size (default: #{Redis::Dump.chunk_size})"
  global :f, :filter, String, "Filter selected keys (passed directly to redis' KEYS command)"
  global :b, :base64, "Encode key values as base64 (useful for binary values)" do
    Redis::Dump.with_base64 = true
  end
  global :O, :without_optimizations, "Disable run time optimizations" do
    Redis::Dump.with_optimizations = false
  end
  global :V, :version, "Display version" do
    puts "redis-dump v#{Redis::Dump::VERSION.to_s}"
    exit 0
  end
  global :D, :debug do
    Redis::Dump.debug = true
  end
  global :nosafe do
    Redis::Dump.safe = false
  end

  before do |obj|
    obj.global.uri ||= ENV['REDIS_URI']
    obj.global.uri ||= 'redis://%s:%s' % [Redis::Dump.host, Redis::Dump.port]
    obj.global.uri = 'redis://' << obj.global.uri unless obj.global.uri.match(/^redis:\/\//)
    obj.global.database &&= obj.global.database.to_i
    obj.global.database ||= (0..15)
    Redis::Dump.chunk_size = obj.global.count if obj.global.count
    Redis::Dump.ld "redis_uri: #{obj.global.uri} (#{obj.global.database})"
    Redis::Dump.ld "Process: #{$$}; Memory: #{Redis::Dump.memory_usage}" if Redis::Dump.debug
  end

  after do |obj|
    Redis::Dump.ld "Process: #{$$}; Memory: #{Redis::Dump.memory_usage}" if Redis::Dump.debug
    sleep obj.global.sleep.to_i if obj.global.sleep
  end

  usage "redis-dump > dumpfile_full.json"
  usage "redis-dump -d 15 > dumpfile_db15.json"
  usage "redis-dump -d 15 -c 100_000 > dumpfile_db15.json"
  command :dump do |obj|
    rd = Redis::Dump.new obj.global.database, obj.global.uri
    obj.global.filter &&= '*%s*' % obj.global.filter
    Redis::Dump.ld " filter #{obj.global.filter}"
    rd.dump(obj.global.filter) do |records|
      puts records
    end
  end

end


begin
  Drydock.run!(ARGV, STDIN) if Drydock.run? && !Drydock.has_run?
rescue RuntimeError => ex
  STDERR.puts ex.message
rescue Drydock::ArgError, Drydock::OptError => ex
  STDERR.puts ex.message
  STDERR.puts ex.usage
rescue Drydock::InvalidArgument => ex
  STDERR.puts ex.message
rescue Drydock::UnknownCommand => ex
  STDERR.puts "Unknown command: %s" % ex.name
rescue Interrupt
  puts $/, "Exiting... "
  exit 1
rescue => ex
  STDERR.puts "ERROR (#{ex.class.to_s}): #{ex.message}"
  STDERR.puts ex.backtrace if Redis::Dump.debug
end
